; mog
;   aims to make your mouse redundant by enabling you to control the pointer
;   and make mouse clicks using only your keyboard.
; Author:  Archie Maskill <archie.maskill@gmail.com>
;
; with thanks to Jordan Sissel for the original idea, and
; Adam Pash for the original AutoHotKey version.
;
; Copyright (C) 2008 Archie Maskill

; This program is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version 2
; of the License, or (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

; TODO:
;    * Write to Jan asking for use of image and add to credits.
;
; For next version:
;    * Have a 'centre' hotkey
;    * undo
;    * IMPROVE SETTINGS DIALOGUE
;        * add color/transparency of include/exclude/locater/crosshair to settings dialogue
;        * change transparency scale to something less arbitrary than 0-255
;          (e.g. percentage in settings window, 0-1 in code)
;    * 9-grid, 4-grid, n-grid variations
;    * implement grids with named cells (grids that are both zooming and uniform)
;    * implement Microsoft Mousekeys
;    * implement a mode that navigates within a window, rather than the entire screen

#SingleInstance,Force ; only one instance can run at once
SetWinDelay,0         ; very small wait after any windowing command

; CONSTANTS
; some global settings
APP_NAME = mog
APP_VERSION = 1.1.0
INI_FILENAME = %APP_NAME%.ini

; Panes define the excluded areas
DIRECTION_RIGHT = 1
DIRECTION_LEFT = 2
DIRECTION_DOWN = 3
DIRECTION_UP = 4
GUI_LOCATER = 5
GUI_CROSSHAIR_VERT = 6
GUI_CROSSHAIR_HORIZ = 7
GUI_SETTINGS = 8
GUI_INCLUDE_AREA = 9

GoSub,SetDefaults

IfNotExist,%INI_FILENAME%  ; create a .ini file if one does not alreay exist
{
    WriteIniFile(INI_FILENAME)
}
ReadIniFile(INI_FILENAME)
Gosub,TrayMenu              ; jump to the TrayMenu subroutine

SysGet, resolutionRight, 78  ; width of virtual screen in pixels
SysGet, resolutionBottom, 79 ; height of virtual screen in pixels

current_x = 0
current_y = 0
dragging = 0
drag_x = 0
drag_y = 0
just_started_navigation = 1
CoordMode, Mouse

HotKey,%activate%,Start,On
HotKey,Escape,EscapeKey,Off
HotKey,%mousekeyup%,MoveUp,Off
HotKey,%mousekeydown%,MoveDown,Off
HotKey,%mousekeyleft%,MoveLeft,Off
HotKey,%mousekeyright%,MoveRight,Off
HotKey,%noclick%,NoClick,Off
HotKey,%leftclick%,LeftClick,Off
HotKey,%rightclick%,RightClick,Off
HotKey,%doubleclick%,DoubleClick,Off
HotKey,%tripleclick%,TripleClick,Off
HotKey,%middleclick%,MiddleClick,Off
HotKey,%wheelup%,WheelUp,Off
HotKey,%wheeldown%,WheelDown,Off
HotKey,%dragclick%,DragClick,Off

; The following hotkey definition MUST be present to prevent Start being executed.
; That left me stumped for a couple of days, but that's OK, Auto Hot Key.
; You do whatever _you_ want.  I don't have anything better to do than to perform
; uncomfortable and time-consuming acrobatics around your quirky corners YOU
; UTTER BASTARD.
^+Enter::
return

EscapeKey:
    GoSub, ExitNavigation
    Exit
return
MoveUp:
    Move(DIRECTION_UP)
    GoSub, RedrawScreen
return
MoveDown:
    Move(DIRECTION_DOWN)
    GoSub, RedrawScreen
return
MoveLeft:
    Move(DIRECTION_LEFT)
    GoSub, RedrawScreen
return
MoveRight:
    Move(DIRECTION_RIGHT)
    GoSub, RedrawScreen
return
ExitNavigation:
    Gosub, DestroyNavigationAreas
    just_started_navigation = 1
    HotKey,%activate%,Start,On
    HotKey,Escape,ExitNavigation,Off
    HotKey,%mousekeyup%,MoveUp,Off
    HotKey,%mousekeydown%,MoveDown,Off
    HotKey,%mousekeyleft%,MoveLeft,Off
    HotKey,%mousekeyright%,MoveRight,Off
    HotKey,%noclick%,NoClick,Off
    HotKey,%leftclick%,LeftClick,Off
    HotKey,%rightclick%,RightClick,Off
    HotKey,%doubleclick%,DoubleClick,Off
    HotKey,%tripleclick%,TripleClick,Off
    HotKey,%middleclick%,MiddleClick,Off
    HotKey,%wheelup%,WheelUp,Off
    HotKey,%wheeldown%,WheelDown,Off
    HotKey,%dragclick%,DragClick,Off
return
NoClick:
    Gosub, DestroyNavigationAreas
    MouseMove, current_x, current_y, 0
    Gosub, Start
return
LeftClick:
    Gosub, DestroyNavigationAreas
    MouseMove, current_x, current_y, 0
    Click left
    Gosub, Start
return
RightClick:
    Gosub, DestroyNavigationAreas
    MouseMove, current_x, current_y, 0
    Click right
    Exit
return
DoubleClick:
    Gosub, DestroyNavigationAreas
    MouseMove, current_x, current_y, 0
    Click 2
    Gosub, Start
return
TripleClick:
    Gosub, DestroyNavigationAreas
    MouseMove, current_x, current_y, 0
    Click 3
    Exit
return
MiddleClick:
    Gosub, DestroyNavigationAreas
    MouseMove, current_x, current_y, 0
    Click middle
    Gosub, Start
return
WheelUp:
    Gosub, DestroyNavigationAreas
    MouseMove, current_x, current_y, 0
    Click WheelUp
    Gosub, Start
return
WheelDown:
    Gosub, DestroyNavigationAreas
    MouseMove, current_x, current_y, 0
    Click WheelDown
    Gosub, Start
return
DragClick:
    if dragging
    {
        Gosub, DestroyNavigationAreas
        dragging = 0
        MouseClickDrag, L, %drag_x%, %drag_y%, %current_x%, %current_y%, 0
        Gosub, Start
    }
    else
    {
        Gosub, DestroyNavigationAreas
        dragging = 1
        drag_x := current_x
        drag_y := current_y
        Gosub, Start
    }
return


Start:
    if do_not_start
    {
        return
    }
    min_x := 0
    max_x := resolutionRight
    min_y := 0
    max_y := resolutionBottom
    MouseGetPos, current_x, current_y

    CreateExcludedArea(DIRECTION_UP,    excluded_area_color, transparencyon, excluded_area_transparency)
    CreateExcludedArea(DIRECTION_DOWN,  excluded_area_color, transparencyon, excluded_area_transparency)
    CreateExcludedArea(DIRECTION_LEFT,  excluded_area_color, transparencyon, excluded_area_transparency)
    CreateExcludedArea(DIRECTION_RIGHT, excluded_area_color, transparencyon, excluded_area_transparency)
    CreateCrossHair(GUI_CROSSHAIR_VERT,  crosshair_color, crosshair_transparency)
    CreateCrossHair(GUI_CROSSHAIR_HORIZ, crosshair_color, crosshair_transparency)
    If highlight_included_area
    {
        CreateIncludedArea(included_area_color, included_area_transparency)
    }
    if locater_enabled and just_started_navigation
    {
        CreateLocater(locater_color, locater_transparency)
        LocatePointer(current_x, current_y, locater_color, locater_transparency)
        just_started_navigation = 0
    }
    HotKey,%activate%,Start,Off
    HotKey,Escape,EscapeKey,On
    HotKey,%mousekeyup%,MoveUp,On
    HotKey,%mousekeydown%,MoveDown,On
    HotKey,%mousekeyleft%,MoveLeft,On
    HotKey,%mousekeyright%,MoveRight,On
    HotKey,%noclick%,NoClick,On
    HotKey,%leftclick%,LeftClick,On
    HotKey,%rightclick%,RightClick,On
    HotKey,%doubleclick%,DoubleClick,On
    HotKey,%tripleclick%,TripleClick,On
    HotKey,%middleclick%,MiddleClick,On
    HotKey,%wheelup%,WheelUp,On
    HotKey,%wheeldown%,WheelDown,On
    HotKey,%dragclick%,DragClick,On
    GoSub, RedrawScreen
return

RedrawScreen:
    If hide_excluded_areas
    {
        ReshapeSplashimage(DIRECTION_UP, 0, max_y, resolutionRight, Ceil(resolutionBottom - max_y))
        ReshapeSplashimage(DIRECTION_DOWN, 0, 0, resolutionRight, min_y)
        ReshapeSplashimage(DIRECTION_LEFT, max_x, 0, Ceil(resolutionRight - max_x), resolutionBottom)
        ReshapeSplashimage(DIRECTION_RIGHT, 0, 0, min_x, resolutionBottom)
    }
    if highlight_included_area
    {
        ReshapeSplashimage(GUI_INCLUDE_AREA, min_x, min_y, max_x-min_x, max_y-min_y)
    }
    Crosshair(current_x, current_y, dragging)
Return


CreateLocater(color, transparency)
{
    global GUI_LOCATER
    Splashimage,%GUI_LOCATER%:, B1 H1 W1 X0 Y0 CW%color%,,,%GUI_LOCATER%
    ahk_transparency := 255 - transparency
    WinSet,Transparent,%ahk_transparency%,%GUI_LOCATER%
}


CreateCrossHair(crosshair, color, transparency)
{
    Splashimage,%crosshair%:, B H1 W1 X0 Y0 CW%color%,,,%crosshair%
    ahk_transparency := 255 - transparency
    WinSet,Transparent,%ahk_transparency%,%crosshair%
}


CreateExcludedArea(excludeArea, color, transparencyon, transparency)
{
    Splashimage,%excludeArea%:, B H W1 X0 Y0 CW%color%,,,%excludeArea%
    if transparencyon
    {
        ahk_transparency := 255 - transparency
        WinSet,Transparent,%ahk_transparency%,%excludeArea%
    }
    return
}


CreateIncludedArea(color, transparency)
{
    global GUI_INCLUDE_AREA
    Splashimage,%GUI_INCLUDE_AREA%:, B1 H1 W1 X0 Y0 CW%color%,,,%GUI_INCLUDE_AREA%
    ahk_transparency := 255 - transparency
    WinSet,Transparent,%ahk_transparency%,%GUI_INCLUDE_AREA%
}


ReshapeSplashimage(excludeArea,x,y,width,height)
{
    WinMove,%excludeArea%,,%x%,%y%,%width%,%height%
}


Move(direction)
{
    global min_y, max_y, min_x, max_x
    global DIRECTION_UP, DIRECTION_DOWN, DIRECTION_LEFT, DIRECTION_RIGHT
    global current_x, current_y
    if (direction = DIRECTION_UP)
    {
        max_y := current_y
        new_x := current_x
        new_y := min_y + (max_y - min_y)/2
    }
    else if (direction = DIRECTION_DOWN)
    {
        min_y := current_y
        new_x := current_x
        new_y := min_y + (max_y - min_y)/2
    }
    else if (direction = DIRECTION_LEFT)
    {
        max_x := current_x
        new_x := min_x + (max_x - min_x)/2
        new_y := current_y
    }
    else if (direction = DIRECTION_RIGHT)
    {
        min_x := current_x
        new_x := min_x + (max_x - min_x)/2
        new_y := current_y
    }

    current_x := new_x
    current_y := new_y
}


DestroyNavigationAreas:
    Splashimage, %DIRECTION_UP%: Off
    Splashimage, %DIRECTION_DOWN%: Off
    Splashimage, %DIRECTION_LEFT%: Off
    Splashimage, %DIRECTION_RIGHT%: Off
    Splashimage, %GUI_INCLUDE_AREA%: Off
    Splashimage, %GUI_CROSSHAIR_VERT%: Off
    Splashimage, %GUI_CROSSHAIR_HORIZ%: Off
    Splashimage, %GUI_LOCATER%: Off
return


; draws a crosshair at given coordinates within the inclusion area
Crosshair(x,y,dragging)
{
    global resolutionRight, resolutionBottom, GUI_CROSSHAIR_VERT, GUI_CROSSHAIR_HORIZ

    width := resolutionRight
    height := resolutionBottom
    posx = 0
    posy = 0
    if dragging
    {
        thickness = 3
    }
    ReshapeSplashimage(GUI_CROSSHAIR_HORIZ,  posx, y, width, thickness)
    ReshapeSplashimage(GUI_CROSSHAIR_VERT, x, posy, thickness, height)
}


LocatePointer(x,y, color, transparency)
{
    global GUI_LOCATER
    delay := 100
    size  := 100
    x_pos := Ceil(x - size/2)
    y_pos := Ceil(y - size/2)

    Loop, 2
    {
        Splashimage, %GUI_LOCATER%: Show
        ReshapeSplashimage(GUI_LOCATER, x_pos, y_pos, size, size)
        Sleep, %delay%
        WinHide, %GUI_LOCATER%
        Sleep, %delay%
    }
}


SetDefaults:
    ; set up default keybindings and options
    DEFAULT_activate = ^!Z
    activate := DEFAULT_activate

    ; movement
    DEFAULT_mousekeyup = k
    mousekeyup := DEFAULT_mousekeyup 
    DEFAULT_mousekeyleft = h
    mousekeyleft := DEFAULT_mousekeyleft 
    DEFAULT_mousekeyright = l
    mousekeyright := DEFAULT_mousekeyright 
    DEFAULT_mousekeydown = j
    mousekeydown := DEFAULT_mousekeydown 

    ; clicks
    DEFAULT_noclick = \
    noclick := DEFAULT_noclick
    DEFAULT_leftclick = z
    leftclick := DEFAULT_leftclick 
    DEFAULT_rightclick = c
    rightclick := DEFAULT_rightclick 
    DEFAULT_middleclick = x
    middleclick := DEFAULT_middleclick 
    DEFAULT_doubleclick = d
    doubleclick := DEFAULT_doubleclick 
    DEFAULT_tripleclick = t
    tripleclick := DEFAULT_tripleclick 
    DEFAULT_dragclick = p
    dragclick := DEFAULT_dragclick 
    DEFAULT_wheelup = w
    wheelup := DEFAULT_wheelup 
    DEFAULT_wheeldown = s
    wheeldown := DEFAULT_wheeldown 

    ; options
    DEFAULT_hide_excluded_areas = 1
    hide_excluded_areas := DEFAULT_hide_excluded_areas 
    DEFAULT_highlight_included_area = 0
    highlight_included_area := DEFAULT_highlight_included_area 
    DEFAULT_locater_enabled = 1
    locater_enabled := DEFAULT_locater_enabled 
    DEFAULT_transparencyon = 0
    transparencyon := DEFAULT_transparencyon 

    ; colours and transparencies
    DEFAULT_excluded_area_color = 000000
    excluded_area_color := DEFAULT_excluded_area_color 
    DEFAULT_excluded_area_transparency = 150 ; 0-255
    excluded_area_transparency := DEFAULT_excluded_area_transparency 
    DEFAULT_included_area_color = FFFFFF
    included_area_color := DEFAULT_included_area_color 
    DEFAULT_included_area_transparency = 200
    included_area_transparency := DEFAULT_included_area_transparency 
    DEFAULT_locater_transparency = 100
    locater_transparency := DEFAULT_locater_transparency 
    DEFAULT_locater_color = 00ff00
    locater_color := DEFAULT_locater_color 
    DEFAULT_crosshair_color = AA0000
    crosshair_color := DEFAULT_crosshair_color 
    DEFAULT_crosshair_transparency = 70
    crosshair_transparency := DEFAULT_crosshair_transparency 
return


WriteIniFile(filename)
{
    ; write values to the specified ini file
    global activate
    global mousekeyup, mousekeydown, mousekeyleft, mousekeyright
    global noclick, leftclick, rightclick, middleclick, doubleclick, tripleclick, wheelup, wheeldown, dragclick
    global hide_excluded_areas, highlight_included_area, locater_enabled, transparencyon
    global excluded_area_color, excluded_area_transparency
    global included_area_color, included_area_transparency
    global locater_color, locater_transparency
    global crosshair_color, crosshair_transparency

    IniWrite,%activate%,%filename%,Settings,activate             ; activates the application

    ; movement
    IniWrite,%mousekeyup%,%filename%,Settings,mousekeyup
    IniWrite,%mousekeydown%,%filename%,Settings,mousekeydown
    IniWrite,%mousekeyleft%,%filename%,Settings,mousekeyleft
    IniWrite,%mousekeyright%,%filename%,Settings,mousekeyright

    ; clicks
    IniWrite,%leftclick%,%filename%,Settings,leftclick
    IniWrite,%rightclick%,%filename%,Settings,rightclick
    IniWrite,%middleclick%,%filename%,Settings,middleclick

    IniWrite,%doubleclick%,%filename%,Settings,doubleclick
    IniWrite,%tripleclick%,%filename%,Settings,tripleclick
    IniWrite,%noclick%,%filename%,Settings,noclick     ; no click (move the mouse, but don't click)

    IniWrite,%wheelup%,%filename%,Settings,wheelup     ; mouse wheel up
    IniWrite,%wheeldown%,%filename%,Settings,wheeldown ; mouse wheel down
    IniWrite,%dragclick%,%filename%,Settings,dragclick ; start/stop dragging the mouse

    ; options
    IniWrite,%hide_excluded_areas%,%filename%,Settings,hide_excluded_areas ; hide the areas of the screen that have been ruled out
    IniWrite,%highlight_included_area%,%filename%,Settings,highlight_included_area
    IniWrite,%locater_enabled%,%filename%,Settings,locater_enabled         ; highlight the pointer's location
    IniWrite,%transparencyon%,%filename%,Settings,transparencyon ; transparency on

    ; colours and transparencies
    IniWrite,%excluded_area_color%,%filename%,Settings,excluded_area_color   ; colour of the areas that get hidden when excluded
    IniWrite,%excluded_area_transparency%,%filename%,Settings,excluded_area_transparency
    IniWrite,%included_area_color%,%filename%,Settings,included_area_color
    IniWrite,%included_area_transparency%,%filename%,Settings,included_area_transparency
    IniWrite,%locater_color%,%filename%,Settings,locater_color
    IniWrite,%locater_transparency%,%filename%,Settings,locater_transparency
    IniWrite,%crosshair_color%,%filename%,Settings,crosshair_color
    IniWrite,%crosshair_transparency%,%filename%,Settings,crosshair_transparency
}


ReadIniFile(filename)
{
    ; read values from the specified ini file
    global activate
    global mousekeyup, mousekeydown, mousekeyleft, mousekeyright
    global noclick, leftclick, rightclick, middleclick, doubleclick, tripleclick, wheelup, wheeldown, dragclick
    global hide_excluded_areas, highlight_included_area, locater_enabled, transparencyon
    global excluded_area_color, excluded_area_transparency
    global included_area_color, included_area_transparency
    global locater_color, locater_transparency
    global crosshair_color, crosshair_transparency

    IniRead,activate,%filename%,Settings,activate

    ; movement
    IniRead,mousekeyup,%filename%,Settings,mousekeyup
    IniRead,mousekeyleft,%filename%,Settings,mousekeyleft
    IniRead,mousekeyright,%filename%,Settings,mousekeyright
    IniRead,mousekeydown,%filename%,Settings,mousekeydown

    ; clicks
    IniRead,noclick,%filename%,Settings,noclick
    IniRead,leftclick,%filename%,Settings,leftclick
    IniRead,doubleclick,%filename%,Settings,doubleclick
    IniRead,rightclick,%filename%,Settings,rightclick
    IniRead,middleclick,%filename%,Settings,middleclick
    IniRead,tripleclick,%filename%,Settings,tripleclick
    IniRead,dragclick,%filename%,Settings,dragclick
    IniRead,wheelup,%filename%,Settings,wheelup
    IniRead,wheeldown,%filename%,Settings,wheeldown

    ; options
    IniRead,hide_excluded_areas,%filename%,Settings,hide_excluded_areas
    IniRead,highlight_included_area,%filename%,Settings,highlight_included_area
    IniRead,locater_enabled,%filename%,Settings,locater_enabled
    IniRead,transparencyon,%filename%,Settings,transparencyon

    ; colours and transparencies
    IniRead,excluded_area_color,%filename%,Settings,excluded_area_color
    IniRead,excluded_area_transparency,%filename%,Settings,excluded_area_transparency
    IniRead,included_area_color,%filename%,Settings,included_area_color
    IniRead,included_area_transparency,%filename%,Settings,included_area_transparency
    IniRead,locater_color,%filename%,Settings,locater_color
    IniRead,locater_transparency,%filename%,Settings,locater_transparency
    IniRead,crosshair_color,%filename%,Settings,crosshair_color
    IniRead,crosshair_transparency,%filename%,Settings,crosshair_transparency
}


TrayMenu:
    Menu,Tray,NoStandard             ; removes all standard options from menu
    Menu,Tray,DeleteAll              ; removes all custom options from menu
    Menu,Tray,Add,&About,ABOUT
    Menu,Tray,Add,&Help,HELP
    Menu,Tray,Add,                   ; separator
    Menu,Tray,Add,&Settings,SETTINGS ; Settings... option (S is an accelerator), linked to the SETTINGS subroutine
    Menu,Tray,Add,E&xit,EndApp       ; add an Exit option (X is an accelerator), linked to the EXIT subroutine
    Menu,Tray,Default,&Settings      ; Settings is the default option (when tray icon double clicked, Settings option selected)
    Menu,Tray,Tip,%APP_NAME% v%APP_VERSION%  ; When hovering over the tray icon, tooltip displays the application name
Return


MakeHumanReadable(input_var)
{
    StringReplace,output_var,input_var,+,Shift +%A_Space%
    StringReplace,output_var,output_var,^,Ctrl +%A_Space%
    StringReplace,output_var,output_var,!,Alt +%A_Space%
    return output_var
}


SETTINGS:
    do_not_start = 1
    HotKey,%activate%,Start,Off
    GoSub, ExitNavigation
    Gui,%GUI_SETTINGS%: Destroy

    ; Hotkey activate
    Gui,%GUI_SETTiNGS%: Font, Bold
    Gui,%GUI_SETTINGS%: Add,Text,bold xm+75 ym+13, Activate:
    Gui,%GUI_SETTiNGS%: Font, Norm
    Gui,%GUI_SETTINGS%: Add,Hotkey,xp+55 yp-4 w180 vsactivate, %activate%

    ;;;;;;;;;;;;;;;;;;;;;;;;;;
    ; Movement keys Groupbox ;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;
    Gui,%GUI_SETTINGS%: Add,GroupBox,xm+0 ym+42 w130 h120,&Movement keys
    ; Hotkey UP
    Gui,%GUI_SETTINGS%: Add, Text, xp+20 yp+30, Up:
    Gui,%GUI_SETTINGS%: Add,Hotkey,xp+40 yp-4 w50 vsmousekeyup, %mousekeyup%

    ; Hotkey DOWN
    Gui,%GUI_SETTINGS%: Add, Text, xp-40 yp+25, Down:
    Gui,%GUI_SETTINGS%: Add,Hotkey,xp+40 yp-4 w50 vsmousekeydown, %mousekeydown%

    ; Hotkey LEFT
    Gui,%GUI_SETTINGS%: Add, Text, xp-40 yp+25, Left:
    Gui,%GUI_SETTINGS%: Add,Hotkey,xp+40 yp-4 w50 vsmousekeyleft, %mousekeyleft%

    ; Hotkey RIGHT
    Gui,%GUI_SETTINGS%: Add, Text, xp-40 yp+25, Right:
    Gui,%GUI_SETTINGS%: Add,Hotkey,xp+40 yp-4 w50 vsmousekeyright, %mousekeyright%
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ; End Movement keys Groupbox ;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



    ;;;;;;;;;;;;;;;;;;;;
    ; Options Groupbox ;
    ;;;;;;;;;;;;;;;;;;;;
    Gui,%GUI_SETTINGS%: Add, GroupBox, xm+150 ym+42 w250 h120, Options
    Gui,%GUI_SETTINGS%: Add, Checkbox, xp+10 yp+30 vslocater_enabled Checked%locater_enabled%, Highlight pointer location when activated
    Gui,%GUI_SETTINGS%: Add, Checkbox, xp+0 yp+20 vshide_excluded_areas Checked%hide_excluded_areas%, Hide areas that are off-limits
    Gui,%GUI_SETTINGS%: Add, Checkbox, xp+0 yp+20 vstransparencyon Checked%transparencyon%, Hidden areas are partially visible
    Gui,%GUI_SETTINGS%: Add, Checkbox, xp+0 yp+20 vshighlight_included_area Checked%highlight_included_area%, Highlight the remaining area
    ;;;;;;;;;;;;;;;;;;;;;;;;
    ; End Options Groupbox ;
    ;;;;;;;;;;;;;;;;;;;;;;;;



    ;;;;;;;;;;;;;;;;;;;;;;;;
    ; Mouse click Groupbox ;
    ;;;;;;;;;;;;;;;;;;;;;;;;
    Gui,%GUI_SETTINGS%: Add,GroupBox,xm+0 ym+175 w400 h90,&Mouse clicks

    ; Hotkey LEFTCLICK
    Gui,%GUI_SETTINGS%: Add, Text, xp+10 yp+20, Left click:
    Gui,%GUI_SETTINGS%: Add, Hotkey,xp+65 yp-2 w50 vsleftclick, %leftclick%

    ; Hotkey RIGHTCLICK
    Gui,%GUI_SETTINGS%: Add, Text, xp-65 yp+25, Right click:
    Gui,%GUI_SETTINGS%: Add, Hotkey,xp+65 yp-2 w50 vsrightclick, %rightclick%

    ; Hotkey MIDDLECLICK
    Gui,%GUI_SETTINGS%: Add, Text, xp-65 yp+25, Middle click:
    Gui,%GUI_SETTINGS%: Add, Hotkey,xp+65 yp-2 w50 vsmiddleclick, %middleclick%

    ; Hotkey DOUBLECLICK
    Gui,%GUI_SETTINGS%: Add, Text, xp+60 yp-44, Double click:
    Gui,%GUI_SETTINGS%: Add, Hotkey,xp+65 yp-2 w50 vsdoubleclick, %doubleclick%

    ; Hotkey TRIPLECLICK
    Gui,%GUI_SETTINGS%: Add, Text, xp-65 yp+25, Triple click:
    Gui,%GUI_SETTINGS%: Add, Hotkey,xp+65 yp-2 w50 vstripleclick, %tripleclick%
    
    ; Hotkey NOCLICK
    Gui,%GUI_SETTINGS%: Add, Text, xp-65 yp+25, No click:
    Gui,%GUI_SETTINGS%: Add, Hotkey,xp+65 yp-2 w50 vsnoclick, %noclick%

    ; Hotkey WHEELUP
    Gui,%GUI_SETTINGS%: Add, Text, xp+60 yp-44, Wheel up:
    Gui,%GUI_SETTINGS%: Add, Hotkey,xp+65 yp-2 w50 vswheelup, %wheelup%

    ; Hotkey WHEELDOWN
    Gui,%GUI_SETTINGS%: Add, Text, xp-65 yp+25, Wheel down:
    Gui,%GUI_SETTINGS%: Add, Hotkey,xp+65 yp-2 w50 vswheeldown, %wheeldown%

    ; Hotkey DRAGCLICK
    Gui,%GUI_SETTINGS%: Add, Text, xp-65 yp+25, Dragging:
    Gui,%GUI_SETTINGS%: Add, Hotkey,xp+65 yp-2 w50 vsdragclick, %dragclick%
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ; End Mouse Click Groupbox ;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    Gui,%GUI_SETTINGS%: Add, Button,xm+0 y+20 GSettingsRestoreDefaults,Restore &Defaults
    Gui,%GUI_SETTINGS%: Add, Button,xm+244 yp+0 w75 GSettingsOK,&OK
    Gui,%GUI_SETTINGS%: Add, Button,xp+80 yp+0 w75 GSettingsCancel,&Cancel
    Gui,%GUI_SETTINGS%: Show,,%APP_NAME% Settings
Return


RemoveNumpad(input_var)
{
    StringReplace, output_var, input_var, Numpad,,All
    return output_var
}


SettingsRestoreDefaults:
    GuiControl, Text, sactivate, %DEFAULT_activate%

    GuiControl, Text, smousekeyup, %DEFAULT_mousekeyup%
    GuiControl, Text, smousekeyleft, %DEFAULT_mousekeyleft%
    GuiControl, Text, smousekeyright, %DEFAULT_mousekeyright%
    GuiControl, Text, smousekeydown, %DEFAULT_mousekeydown%

    GuiControl, Text, snoclick, %DEFAULT_noclick%
    GuiControl, Text, sleftclick, %DEFAULT_leftclick%
    GuiControl, Text, srightclick, %DEFAULT_rightclick%
    GuiControl, Text, smiddleclick, %DEFAULT_middleclick%
    GuiControl, Text, sdoubleclick, %DEFAULT_doubleclick%
    GuiControl, Text, stripleclick, %DEFAULT_tripleclick%
    GuiControl, Text, sdragclick, %DEFAULT_dragclick%
    GuiControl, Text, swheelup, %DEFAULT_wheelup%
    GuiControl, Text, swheeldown, %DEFAULT_wheeldown%

    GuiControl,, shide_excluded_areas, %DEFAULT_hide_excluded_areas%
    GuiControl,, shighlight_included_area, %DEFAULT_highlight_included_area%
    GuiControl,, slocater_enabled, %DEFAULT_locater_enabled%
    GuiControl,, stransparencyon, %DEFAULT_transparencyon%

    GuiControl, Text, sexcluded_area_color, %DEFAULT_excluded_area_color%
    GuiControl, Text, sexcluded_area_transparency, %DEFAULT_excluded_area_transparency%
    GuiControl, Text, sincluded_area_color, %DEFAULT_included_area_color%
    GuiControl, Text, sincluded_area_transparency, %DEFAULT_included_area_transparency%
    GuiControl, Text, slocater_transparency, %DEFAULT_locater_transparency%
    GuiControl, Text, slocater_color, %DEFAULT_locater_color%
    GuiControl, Text, scrosshair_color, %DEFAULT_crosshair_color%
    GuiControl, Text, scrosshair_transparency, %DEFAULT_crosshair_transparency%
Return


SettingsOK:
    Gui,%GUI_SETTINGS%: Submit
    If sactivate<>
        activate:=sactivate
    If smousekeyup<>
        mousekeyup := RemoveNumpad(smousekeyup)
    If smousekeyleft<>
        mousekeyleft := RemoveNumpad(smousekeyleft)
    If smousekeyright<>
        mousekeyright := RemoveNumpad(smousekeyright)
    If smousekeydown<>
        mousekeydown := RemoveNumpad(smousekeydown)
    If snoclick<>
        noclick := RemoveNumpad(snoclick)
    If sleftclick<>
        leftclick := RemoveNumpad(sleftclick)
    If srightclick<>
        rightclick := RemoveNumpad(srightclick)
    If sdoubleclick<>
        doubleclick := RemoveNumpad(sdoubleclick)
    If stripleclick<>
        tripleclick := RemoveNumpad(stripleclick)
    If swheelup<>
        wheelup := RemoveNumpad(swheelup)
    If swheeldown<>
        wheeldown := RemoveNumpad(swheeldown)
    If sdragclick<>
        dragclick := RemoveNumpad(sdragclick)
    If smiddleclick<>
        middleclick := RemoveNumpad(smiddleclick)

    HotKey,%activate%,Start,On
    if slocater_enabled<>
        locater_enabled := slocater_enabled
    if shide_excluded_areas<>
        hide_excluded_areas := shide_excluded_areas
    if stransparencyon<>
        transparencyon := stransparencyon
    if shighlight_included_area<>
        highlight_included_area := shighlight_included_area

    WriteIniFile(INI_FILENAME)
    Gui,%GUI_SETTINGS%: Destroy
    Reload
Return


SettingsCancel:
    HotKey,%activate%,Start,On
    do_not_start = 0
    Gui,%GUI_SETTINGS%: Destroy
Return


ABOUT:
    w = 60
    h = 20
    m1 = 20
    m2 = 10
    Gui,Destroy
    Gui,Font,Bold
    Gui,Add,Text,xm+120 ym+10,%APP_NAME% v%APP_VERSION%
    Gui,Font,Norm

    Gui,Font,Bold
    Gui,Add,Text,xm+%m1% yp+30,Author:
    Gui,Font,Norm

    Gui,Add,Text,xp+%w% yp+0,Archie Maskill

    Gui,Font,Bold
    Gui,Add,Text,xm+%m1% yp+%h%,Website:
    Gui,Font,Norm

    Gui,Font,underline
    Gui,Add,Text,xp+%w% yp+0 cBlue gLaunchWebsite,http://archiemaskill.wordpress.com
    Gui,Font,Norm

    Gui,Font,Bold
    Gui,Add,Text,xm+%m1% yp+%h%,Email:
    Gui,Font,Norm

    Gui,Font,underline
    Gui,Add,Text,xp+%w% yp+0 cBlue gLaunchEmail,archie.maskill@gmail.com
    Gui,Font,Norm
    
    Gui,Add,Text,xm+%m2% yp+30,%APP_NAME% aims to make your mouse redundant by enabling you to
    Gui,Add,Text,xm+%m2% yp+15,control the pointer using only your keyboard.

    Gui,Add,Text,xm+%m2% yp+30,The word '%APP_NAME%' is British slang for a cat, the natural enemy of
    Gui,Add,Text,xm+%m2% yp+15,the mouse.  It can also mean "to go from one place to another",
    Gui,Add,Text,xm+%m2% yp+15,and so it is doubly appropriate.

    Gui,Add,Text,xm+%m2% yp+30,It's something of a research project at the moment, and is
    Gui,Add,Text,xm+%m2% yp+15,written as a working prototype using AutoHotKey.  I'll be
    Gui,Add,Text,xm+%m2% yp+15,adding plenty more features as I explore different methods of
    Gui,Add,Text,xm+%m2% yp+15,efficiently and painlessly navigating the screen using only the
    Gui,Add,Text,xm+%m2% yp+15,keyboard.  If these prove successful, I hope to bring them to
    Gui,Add,Text,xm+%m2% yp+15,platforms other than Windows.

    Gui,Add,Text,xm+%m2% yp+30,I'd like to thank Adam Pash for 'mouser' (the original AutoHotKey
    Gui,Add,Text,xm+%m2% yp+15,implementation) and Jordan Sissel for the ideas upon which
    Gui,Add,Text,xm+%m2% yp+15,mouser was based.

    Gui,Add,Button,xm+100 yp+30 w100 GJUST_CLOSE,&OK
    Gui,Show,,About %APP_NAME%
Return


HELP:
    h = 15
    Gui,Destroy
    Gui,Add,Text,xm+%m2% ym0,Start by double-clicking %APP_NAME%'s system tray icon to view and change
    Gui,Add,Text,xm+%m2% yp+%h%,the settings, and pick some up/down/left/right keys with which you
    Gui,Add,Text,xm+%m2% yp+%h%,are comfortable.  Pick an 'activate' key combination you like,
    Gui,Add,Text,xm+%m2% yp+%h%,too (try to pick a combination that you don't make use of in any
    Gui,Add,Text,xm+%m2% yp+%h%,of your usual desktop applications).

    Gui,Add,Text,xm+%m2% yp+30,After saving your settings, move your pointer to the centre of your
    Gui,Add,Text,xm+%m2% yp+%h%,screen using your mouse.  Activate %APP_NAME%, using the chosen activation
    Gui,Add,Text,xm+%m2% yp+%h%,keys.  Crosshairs will appear, showing you where your pointer is.
    Gui,Add,Text,xm+%m2% yp+%h%,If at any point you want to abandon %APP_NAME% and regain full control,
    Gui,Add,Text,xm+%m2% yp+%h%,just hit the 'escape' key.

    Gui,Add,Text,xm+%m2% yp+30,%APP_NAME% works by 'throwing away' any screen space you have chosen to move
    Gui,Add,Text,xm+%m2% yp+%h%,away from.  For example, if your pointer is at the screen centre and
    Gui,Add,Text,xm+%m2% yp+%h%,you move upwards, everything that was below the pointer is now
    Gui,Add,Text,xm+%m2% yp+%h%,off-limits.  You cannot navigate back into that space until you
    Gui,Add,Text,xm+%m2% yp+%h%,restart the navigation.  The crosshairs are then placed at the very
    Gui,Add,Text,xm+%m2% yp+%h%,centre of the remaining space.  Using this method, you can very
    Gui,Add,Text,xm+%m2% yp+%h%,quickly move the pointer to the area you're interested in.  It's
    Gui,Add,Text,xm+%m2% yp+%h%,a lot clearer just to try it out for yourself!

    Gui,Add,Text,xm+%m2% yp+30,Once the pointer is were you want it to be, you can left-click,
    Gui,Add,Text,xm+%m2% yp+%h%,right-click, double-click, etc. using all those clicking options
    Gui,Add,Text,xm+%m2% yp+%h%,you saw in the Settings window.  Once a click operation takes place,
    Gui,Add,Text,xm+%m2% yp+%h%,%APP_NAME% restarts the navigation - that is, the entire screen space is
    Gui,Add,Text,xm+%m2% yp+%h%,available for navigation again (right-click is an exception to this
    Gui,Add,Text,xm+%m2% yp+%h%,rule because you'll usually want to navigate a menu with cursor keys
    Gui,Add,Text,xm+%m2% yp+%h%,at that point).

    Gui,Add,Button,xm+120 yp+30 w100 GJUST_CLOSE,&OK
    Gui,Show,,%APP_NAME% Help!
Return


JUST_CLOSE:
    Gui, Destroy
Return

LaunchWebsite:
    Run www.archiemaskill.wordpress.com
Return


LaunchEmail:
    Run mailto:archie.maskill@gmail.com
Return


EndApp:
    just_started_navigation = 1
    ExitApp
return

